/**
 * 
 */
package orderProcessingProcess.client.junit;


import static org.junit.Assert.fail;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import orderProcessingProcess.exceptions.faults.ItemUnavailableFault;
import orderProcessingProcess.exceptions.faults.UnknownItemFault;
import orderProcessingProcess.exceptions.faults.UnknownOrderFault;
import orderProcessingProcess.model.Address;
import orderProcessingProcess.model.Customer;
import orderProcessingProcess.model.Item;
import orderProcessingProcess.model.Order;
import orderProcessingProcess.model.Payment_Preference;
import orderProcessingProcess.server.OrderManagementService;

import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;


/**
 * @author charly
 *
 */
public final class TestOrderManagementService {

    /*private static final QName SERVICE_NAME 
        = new QName("http://infosys.tuwien.ac.at/ait09/ass1/dto/", "orderservice");
    private static final QName PORT_NAME 
        = new QName("http://infosys.tuwien.ac.at/ait09/ass1/dto/", "orderservicePort");
*/
	private static OrderManagementService client;
    
    @BeforeClass
    public static void init()
    {
    	JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
    	factory.getInInterceptors().add(new LoggingInInterceptor());
    	factory.getOutInterceptors().add(new LoggingOutInterceptor());
    	factory.setServiceClass(OrderManagementService.class);
    	factory.setAddress("http://localhost:8083/orderservice");
    	client = (OrderManagementService) factory.create();
    	createData();
    }

    @Test
    public void check_availabilityTest()
    {
    	Item item = new Item(3, "2", new BigDecimal(2.90),null);
    	try 
    	{
			Assert.assertTrue(client.check_availability(item));
		} 
    	catch (UnknownItemFault e) 
    	{
			e.printStackTrace();
		}
    	Item item2 = new Item(12, "2", new BigDecimal(2.90),null);
    	
    	try 
    	{
			Assert.assertFalse(client.check_availability(item2));
		} 
    	catch (UnknownItemFault e) 
    	{
			e.printStackTrace();
		}
    }
    
    @Test
    public void check_availability_UnknownItemFault_Test()
    {
    	try
    	{
    		client.check_availability(new Item(3, "100", new BigDecimal(2.90),null));
    		fail();
    	}
    	catch(UnknownItemFault e)
    	{
    		Assert.assertTrue(true); //not needed, but should highlight that an UnknownItemFault is expected
    	}
    }
    
    @Test
    public void placeOrderTest()
    {
    	Customer c1 = new Customer("1", "name1", new Address("1","street1", "city1", 12, 2, "zip_code1"), Payment_Preference.Bank_Transfer);
    	Item[] items = new Item[2];
    	
    	items[0] = new Item(10, "1", new BigDecimal(12.90),null);
    	items[1] = new Item(3, "2", new BigDecimal(2.90),null);

    	Order order = null;
    	try
    	{
    		order = client.place_order(items, c1);
    	}
    	catch (ItemUnavailableFault e) {
    		fail();
		}
    	
    	Assert.assertEquals(order.getCustomer(), c1);
    	Assert.assertEquals(order.getId(), "1");
    	Assert.assertEquals(order.getItems().size(), 2);
    	
    }
    
    @Test
    public void placeOrderFaultTest()
    {
    	Customer c1 = new Customer("1", "name1", new Address("1","street1", "city1", 12, 2, "zip_code1"), Payment_Preference.Bank_Transfer);
    	
    	Item[] items = new Item[2];
    	
    	items[0] = new Item(13, "1", new BigDecimal(12.90),null); //13, but only 12 available
    	items[1] = new Item(3, "2", new BigDecimal(2.90),null);

    	try
    	{
    		client.place_order(items, c1);
    		fail();
    	}
    	catch (ItemUnavailableFault e) {
    		Assert.assertTrue(true); //not needed, but should highlight that an UnknownItemFault is expected
		}    	
    }
    
    @Test
    public void isfinishedTest()
    {
    	Customer c1 = new Customer("1", "name1", new Address("1","street1", "city1", 12, 2, "zip_code1"), Payment_Preference.Bank_Transfer);
    	
    	Item[] items = new Item[2];
    	
    	items[0] = new Item(10, "4", new BigDecimal(12.90),null);
    	items[1] = new Item(3, "5", new BigDecimal(2.90),null);

    	Order order = null;
    	try
    	{
    		order = client.place_order(items, c1);
    	}
    	catch (ItemUnavailableFault e) {
    		fail();
			//e.printStackTrace();
		}
    	
    	try 
    	{
			Assert.assertFalse(client.is_finished(order));
			Thread.sleep(10000);
			Assert.assertTrue(client.is_finished(order));
		} 
    	catch (UnknownOrderFault e) 
    	{
    		fail();
		} catch (InterruptedException e) {
			fail();
		}
    }

    @Test
    public void isfinishedFaultTest()
    {
    	Order order = new Order();
    	order.setCustomer(null);
    	order.setId("100");
    	order.setItems(new ArrayList<Item>());
    	order.setOrderDate(Calendar.getInstance().getTime());
    	
    	try 
    	{
			client.is_finished(order);
			fail();
		} 
    	catch (UnknownOrderFault e) 
    	{
    		Assert.assertTrue(true); //not needed, but should highlight that an UnknownItemFault is expected
		}
    }

    /**
     * create test data
     */
    private static void createData()
    {
    	List<Item> items = new ArrayList<Item>();
    	
    	items.add(new Item(12, "1", new BigDecimal(12.90),null));
    	items.add(new Item(3, "2", new BigDecimal(2.90),null));
    	items.add(new Item(5, "3", new BigDecimal(3.90),null));
    	items.add(new Item(200, "4", new BigDecimal(3.90),null));
    	items.add(new Item(50, "5", new BigDecimal(3.90),null));
    	
    	client.insert_test_data(items);
    }

}